#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gfsGlobal.h"
#include "gfsServices.h"

void info()
{
	printf("HELP:\n");
	printf("0 Exit\n");
	printf("1 Init metadata\n");
	printf("2 Open metadata\n");
	printf("3 Get all server\n");
	printf("4 Get available server\n");
	printf("5 Get File Location of existing file\n");
	printf("6 Get File Location of new file\n");
	printf("7 Get file location and move\n");
	printf("8 Save file metadata (write-update)\n");
	printf("9 Save file metadata (delete)\n");
	printf("10 Move file metadata\n");
	printf("11 Save directory metadata\n");
	printf("12 Move directory metadata\n");
	printf("13 Is directory exist\n");
	printf("14 Get item list\n");
	printf("15 Lock metadata\n");
	printf("16 Lock metadata\n");
	printf("17 Get permission\n");
	printf("18 Get permission location\n");
	printf("19 Change permission \n");
	printf("20 Check superuser\n");
	printf("21 Change superuser password\n");
	printf("h for help, c for clear screen, d for debug, s to toggle superuser");

}

//fungsi main===================================================================
int  main()
{
	char input[256];
	char choice[2];
	int choiceInt=0;

	int iResult;
	
	GFS_server server_headPtr, server_now;
	GFS_file file, file2;
	GFS_dir dir, dir2;
	GFS_physical_path phys,phys2,phys_now, phys_now2;
	GFS_item item_headPtr, item_now;

	char mode[32], item[128], lloc[256], item2[128], lloc2[256];
	
	printf("\n");
	
	info();                                         //fungsi untuk mencetak menu
	
	while (1)
	{
		printf("\n? ");
		scanf("%s",choice);
		if  (strcmp(choice,"h")==0)
		{
			info();
			continue;
		}
		else if (strcmp(choice,"c")==0)
		{
			system("clear");
			continue;
		}
		else if (strcmp(choice,"d")==0)
		{
			if (VERBOSE==0)
			{
				VERBOSE=1;
				printf("Debug on.");
			}
			else
			{
				VERBOSE=0;
				printf("Debug off.");
			}
			continue;
		}
		else if (strcmp(choice,"s")==0)
		{
			if (GFS_SUPER_USER==0)
			{
				GFS_SUPER_USER=1;
				printf("Superuser on.");
			}
			else
			{
				GFS_SUPER_USER=0;
				printf("Superuser off.");
			}
			continue;
		}
		choiceInt=atoi(choice);
		
        switch (choiceInt)
		{
			case 0:
				return 0;
				break;
			case 1: 
				//Open metadata database connection---------------------------------------
				printf("gfs_init_metadata() : Init Metadata\n");
				iResult=gfs_init_metadata();
				printf("Return value=%d", iResult);
				checkerror(iResult);
				if (iResult==GFS_SUCCESS)
					printf("gfs_init_metadata(): Metadata connection success\n");
				else if (iResult==-1)
				{
					printf("gfs_init_metadata(): Failed opening configuration file\n");
				}
				else 
				{
					printf("gfs_init_metadata(): Metadata connection failed\n");
				}
				break;
			case 2: 
				//Open metadata database connection---------------------------------------
				printf("gfs_open_metadata() : Open Metadata\n");
				iResult=gfs_open_metadata();
				printf("Return value=%d", iResult);
				checkerror(iResult);
				if (iResult==GFS_SUCCESS)
					printf("gfs_open_metadata(): Metadata connection success\n");
				else
				{
					printf("gfs_open_metadata(): ERROR: Metadata connection failed\n");
				}
				break;
			case 3: ;
				server_headPtr = NULL;
				//STEP 1: get all server-----------------------------------------------------------------
				printf("gfs_get_server() : Get All server\n");
				iResult = gfs_get_all_server(&server_headPtr);
				printf("Return value=%d", iResult);
				checkerror(iResult);
				if (iResult>0)
				{
					//Print
					server_now=NULL;
					if (server_headPtr != NULL)
					{
						server_now = server_headPtr;
						while (server_now)
						{				
							printf("GFS-server : %s | %lld/%lld | %s\n", server_now->hostname, server_now->used, server_now->total, server_now->online);
							server_now=server_now->next;
						}
					}
				}
				else
				 printf("Failed getting all server with value %d\n", iResult);
				break;
			case 4: 
				server_headPtr= NULL;
				//STEP 1: get available server-----------------------------------------------------------------
				printf("gfs_get_server() : Get available server\n");
				iResult = gfs_get_available_server(&server_headPtr);
				printf("Return value=%d", iResult);
				checkerror(iResult);
				if (iResult>0)
				{
					//Print
					server_now=NULL;
					if (server_headPtr != NULL)
					{
						server_now = server_headPtr;
						while (server_now)
						{				
							printf("GFS-server : %s | %lld/%lld | %s\n", server_now->hostname, server_now->used, server_now->total, server_now->online);
							server_now=server_now->next;
						}
					}
				}
				else
				 printf("Failed getting all server with value %d\n", iResult);
				break;
			case 5: 
				//Get file location :existing==============================
				printf("gfs_getFileLocation : Get File Location (existing file)\n");
				iResult=0;
				file=malloc(sizeof(GFS_fileD));

				printf("file name : ");
				scanf("%s", &input);
				strcpy(item, input);
				printf("logical path: ");
				scanf("%s", &input);
				strcpy(lloc, input);
				
				file->pid= 123;
				strcpy(file->mode, "r");
				strcpy(file->file_name, item);
				strcpy(file->logical_loc, lloc);

				iResult=gfs_getFileLocation(file);
				printf("Return value=%d", iResult);
				checkerror(iResult);

				if (phys_now!=NULL)
				{
					phys_now=file->physical_path;
					while (phys_now)
					{
						printf("%s\n", phys_now->url);
						phys_now=phys_now->next;
					}
				}	

				if (iResult<0)
				{
					printf("Something is wrong. see return value\n");
				}
				break;
			case 6: 
				//Get file location :new==============================
				printf("gfs_getFileLocation : Get File Location (new file)\n");
				iResult=0;
				file=malloc(sizeof(GFS_fileD));

				printf("file name : ");
				scanf("%s", &input);
				strcpy(item, input);
				printf("logical path: ");
				scanf("%s", &input);
				strcpy(lloc, input);
				
				file->pid= 129;
				strcpy(file->mode, "w");
				strcpy(file->file_name, item);
				strcpy(file->logical_loc, lloc);

				iResult=gfs_getFileLocation(file);
				printf("Return value=%d", iResult);
				checkerror(iResult);

				phys_now=file->physical_path;
				while (phys_now)
				{
					printf("%s\n", phys_now->url);
					phys_now=phys_now->next;
				}

				if (iResult<0)
				{
					printf("Something is wrong. see return value\n");
				}
				break;
			case 7: 
				//Get file location and move==============================
				printf("gfs_getFileLocationMove : Get File Location and Move\n");
				iResult=0;
				file=malloc(sizeof(GFS_fileD));
				file2=malloc(sizeof(GFS_fileD));
				
				//old file
				file->pid= 129;
				strcpy(file->mode, "d");
				strcpy(file->file_name, "pdf.pdf");
				strcpy(file->logical_loc, "/");

				//new file
				file->pid= 130;
				strcpy(file2->mode, "w");
				strcpy(file2->file_name, "pdf2.pdf");
				strcpy(file2->logical_loc, "/dir");

				iResult=gfs_getFileLocationMove(file, file2);
				printf("Return value=%d", iResult);
				checkerror(iResult);
				
				printf("Old:\n");
				phys_now=file->physical_path;
				while (phys_now)
				{
					printf("%s\n", phys_now->url);
					phys_now=phys_now->next;
				}
				
				printf("New:\n");
				phys_now2=file2->physical_path;
				while (phys_now2)
				{
					printf("%s\n", phys_now2->url);
					phys_now2=phys_now2->next;
				}


				if (iResult<0)
				{
					printf("Something is wrong. see return value\n");
				}
				break;
			case 8:
				//save file metadata
				printf("gfs_saveFileMetadata : Save File Metadata\n");
				iResult=0;
				file=malloc(sizeof(GFS_fileD));
				phys=malloc(sizeof(GFS_physical_pathD));

				printf("item name : ");
				scanf("%s", &input);
				strcpy(item, input);
				printf("logical loc : ");
				scanf("%s", &input);
				strcpy(lloc, input);
				
				file->pid= 131;
				strcpy(file->mode, "w");
				strcpy(file->file_name, item);
				strcpy(file->logical_loc, lloc);
				strcpy(phys->url, "ws-87.rsa.cs.ui.ac.id/gfs/hahaha.txt");
				phys->next=NULL;
				file->physical_path=phys;

				iResult=gfs_saveFileMetadata(file);
				printf("Return value=%d", iResult);
				checkerror(iResult);

				if (iResult==GFS_SUCCESS)
				{
					printf("Success writing to database\n");
				}
				else
				{
					printf("Something is wrong. see return value\n");
				}

				break;
			case 9: 
				//delete file metadata
				printf("gfs_saveFileMetadata : Delete File Metadata\n");
				iResult=0;
				file=malloc(sizeof(GFS_fileD));
				
				printf("item name : ");
				scanf("%s", &input);
				strcpy(item, input);
				printf("logical loc : ");
				scanf("%s", &input);
				strcpy(lloc, input);

				file->pid= 132;
				strcpy(file->mode, "d");
				strcpy(file->file_name, item);
				strcpy(file->logical_loc, lloc);
				strcpy(phys->url, "ws-87.rsa.cs.ui.ac.id/gfs/hahaha.txt");
				phys->next=NULL;
				file->physical_path=phys;
				iResult=gfs_saveFileMetadata(file);
				printf("Return value=%d", iResult);
				checkerror(iResult);

				if (iResult==GFS_SUCCESS)
				{
					printf("Success deleting from database\n");
				}
				else
				{
					//0=nothing is deleted
					printf("Something is wrong. see return value\n");
				}
				break;
			case 10:
				//move file metadata
				printf("gfs_moveFileMetadata : Move File Metadata\n");
				iResult=0;
				file=malloc(sizeof(GFS_fileD));
				phys=malloc(sizeof(GFS_physical_pathD));
				file2=malloc(sizeof(GFS_fileD));
				phys2=malloc(sizeof(GFS_physical_pathD));
				
				printf("item name 1 : ");
				scanf("%s", &input);
				strcpy(item, input);
				printf("logical loc 1 : ");
				scanf("%s", &input);
				strcpy(lloc, input);
				printf("item name 2 : ");
				scanf("%s", &input);
				strcpy(item2, input);
				printf("logical loc 2 : ");
				scanf("%s", &input);
				strcpy(lloc2, input);

				//old file
				file->pid= 129;
				strcpy(file->mode, "d");
				strcpy(file->file_name, item);
				strcpy(file->logical_loc, lloc);
				strcpy(phys->url, "ws-87.rsa.cs.ui.ac.id/gfs/hahaha.txt");
				phys->next=NULL;
				file->physical_path=phys;

				//new file
				file2->pid= 130;
				strcpy(file2->mode, "w");
				strcpy(file2->file_name, item2);
				strcpy(file2->logical_loc, lloc2);
				strcpy(phys2->url, "ws-87.rsa.cs.ui.ac.id/gfs/hahaha.txt");
				phys2->next=NULL;
				file2->physical_path=phys2;

				iResult=gfs_moveFileMetadata(file, file2);
				printf("Return value=%d", iResult);
				checkerror(iResult);
				
				if (iResult==GFS_SUCCESS)
				{
					printf("Success moving in database\n");
				}
				else
				{
					//0=nothing is deleted
					printf("Something is wrong. see return value\n");
				}

				break;
			case 11:
				//save dir metadata
				printf("gfs_saveDirMetadata : Save Dir Metadata\n");
				iResult=0;
				dir=malloc(sizeof(GFS_dirD));

				printf("mode (w,d): ");
				scanf("%s", &input);
				strcpy(mode, input);
				printf("item name : ");
				scanf("%s", &input);
				strcpy(item, input);
				printf("logical loc : ");
				scanf("%s", &input);
				strcpy(lloc, input);
				
				dir->pid= 135;
				strcpy(dir->mode, mode);
				strcpy(dir->dir_name, item);
				strcpy(dir->logical_loc, lloc);

				iResult=gfs_saveDirMetadata(dir);
				printf("Return value=%d", iResult);
				checkerror(iResult);

				if (iResult==GFS_SUCCESS)
				{
					printf("Success writing to database\n");
				}
				else
				{
					printf("Something is wrong. see return value\n");
				}

				break;
			case 12:
				//move dir metadata
				printf("gfs_moveDirMetadata : Move Dir Metadata\n");
				iResult=0;
				dir=malloc(sizeof(GFS_dirD));
				dir2=malloc(sizeof(GFS_dirD));

				printf("item name 1 : ");
				scanf("%s", &input);
				strcpy(item, input);
				printf("logical loc 1 : ");
				scanf("%s", &input);
				strcpy(lloc, input);
				printf("item name 2 : ");
				scanf("%s", &input);
				strcpy(item2, input);
				printf("logical loc 2 : ");
				scanf("%s", &input);
				strcpy(lloc2, input);
				
				//old file
				dir->pid= 139;
				strcpy(dir->mode, "d");
				strcpy(dir->dir_name, item);
				strcpy(dir->logical_loc, lloc);

				//new file
				dir2->pid= 140;
				strcpy(dir2->mode, "w");
				strcpy(dir2->dir_name, item2);
				strcpy(dir2->logical_loc, lloc2);

				iResult=gfs_moveDirMetadata(dir, dir2);
				printf("Return value=%d", iResult);
				checkerror(iResult);
				
				if (iResult==GFS_SUCCESS)
				{
					printf("Success moving in database\n");
				}
				else
				{
					//0=nothing is deleted
					printf("Something is wrong. see return value\n");
				}
				break;
			case 13:
				//is dir exist
				printf("gfs_isDirExist : Is Directory Exist\n");
				iResult=0;
				dir=malloc(sizeof(GFS_dirD));

				printf("item name : ");
				scanf("%s", &input);
				strcpy(item, input);
				printf("logical loc: ");
				scanf("%s", &input);
				
				dir->pid= 133;
				strcpy(dir->dir_name, item);
				strcpy(dir->logical_loc, input);

				iResult=gfs_isDirExist(dir);
				printf("Return value=%d", iResult);
				checkerror(iResult);

				if (iResult==GFS_SUCCESS)
				{
					printf("Directory is exist\n");
				}
				else
				{
					printf("Directory is not exist\n");
				}
				break;
			case 14:
				//get item list
				printf("gfs_getItemList : Get Item List\n");
				iResult=0;
				dir=malloc(sizeof(GFS_dirD));

				printf("gfs_getItemList(GFS_dir dir, GFS_item *item)\n");

				printf("directory name (/ for root): ");
				scanf("%s", &input);
				if (strcmp(input,"/")==0)
					strcpy(dir->dir_name, "");
				else
					strcpy(dir->dir_name, input);

				printf("logical path: ");
				scanf("%s", & input);
				strcpy(dir->logical_loc, input);
				
				item_headPtr=NULL;
				iResult= gfs_getItemList(dir, &item_headPtr);
				printf("Return value=%d", iResult);
				checkerror(iResult);

				if(iResult < GFS_SUCCESS) printf("Failed retrieving list. see return value.");
				else{
					item_now=NULL;
					if (item_headPtr != NULL)
					{
						item_now = item_headPtr;
						while (item_now)
						{							
							printf("%s %s %8lld %s %s %s %s\n", item_now->type, item_now->permission, item_now->size, item_now->owner, item_now->created_date, item_now->modified_date, item_now->item_name);
							 
							//printf("%s \n", item_now->item_name);
							item_now=item_now->next;
						}
					}
				} 							
				
				
				break;
			case 15:
				//lock metadata
				printf("gfs_lockMetadata : Lock Metadata\n");
				iResult=lockmetadata();
				printf("Return value=%d", iResult);
				checkerror(iResult);

				if (iResult>GFS_FAILED)
					printf("Success lock, PID is %d", iResult);
				else
					printf("Something is wrong. see return value\n");
				break;					
			case 16:
				//unlock metadata
				iResult=unlockmetadata();
				printf("Return value=%d", iResult);
				checkerror(iResult);

				if (iResult>GFS_FAILED)
					printf("Success unlocking", iResult);
				else
					printf("Something is wrong. see return value\n");
				break;	
			case 17:
				//get permission
				printf("gfs_get_permission(char *item_name, char *logical_location, char *mode)\n");
				printf("item name : ");
				scanf("%s", &input);
				strcpy(item, input);
				printf("logical loc: ");
				scanf("%s", &input);
				strcpy(lloc, input);
				printf("mode(r,w,x): ");
				scanf("%s", &input);
				strcpy(mode, input);
				iResult=gfs_get_permission(item,lloc,mode);
				printf("Return value=%d", iResult);
				checkerror(iResult);
				if (iResult>GFS_FAILED)
					printf("User is permitted");
				else if (iResult==GFS_FAILED)
					printf("User is not permitted");
				else
					printf("Something is wrong. see return value\n");
				break;
			case 18:
				//get permission
				printf("int gfs_get_permission_location(char *logical_path, char *mode)\n");
				printf("logical path: ");
				scanf("%s", &input);
				strcpy(lloc, input);
				printf("mode(r,w,x): ");
				scanf("%s", &input);
				strcpy(mode, input);
				iResult=gfs_get_permission_location(lloc,mode);
				printf("Return value=%d", iResult);
				checkerror(iResult);
				if (iResult>GFS_FAILED)
					printf("User is permitted");
				else if (iResult==GFS_FAILED)
					printf("User is not permitted");
				else
					printf("Something is wrong. see return value\n");
				break;
			case 19:
				//change permission
				printf("gfs_change_permission(char *item_name, char *logical_location, char *mode)\n");
				printf("item name : ");
				scanf("%s", &input);
				strcpy(item, input);
				printf("logical path: ");
				scanf("%s", &input);
				strcpy(lloc, input);
				printf("mode(77-00): ");
				scanf("%s", &input);
				strcpy(mode, input);
				iResult=gfs_change_permission(item,lloc,mode);
				printf("Return value=%d", iResult);
				checkerror(iResult);
				if (iResult==GFS_SUCCESS)
					printf("Permission changed to %s", mode);
				else
					printf("Something is wrong. see return value\n");
				break;
			case 20:
				//check su
				printf("gfs_superuser_check(char *su_passwd)\n");
				printf("password: ");
				scanf("%s", &input);
				strcpy(item, input);
				iResult=gfs_superuser_check(item);
				printf("Return value=%d", iResult);
				checkerror(iResult);
				if (iResult>GFS_FAILED)
					printf("Superuser password is correct.");
				else if (iResult==GFS_FAILED)
					printf("Wrong superuser password.");
				else
					printf("Something is wrong. see return value\n");
				break;
			case 21:
				//change su pass
				printf("gfs_superuser_chpwd(char *old_pwd, char *new_pwd)\n");
				printf("password: ");
				scanf("%s", &input);
				strcpy(item, input);
				printf("new password: ");
				scanf("%s", &input);
				strcpy(lloc, input);
				iResult=gfs_superuser_chpwd(item,lloc);
				printf("Return value=%d", iResult);
				checkerror(iResult);
				if (iResult>GFS_FAILED)
					printf("Super user password changed.");
				else if (iResult==GFS_FAILED)
					printf("Wrong superuser password.");
				else
					printf("Something is wrong. see return value\n");
				break;
			default: printf("\nMasukkan sesuai petunjuk!\n");
		}
	}

	return 0;
}

int lockmetadata()
{
	char input[256];
	char lm[32], am[32], item[128], lloc[256];
	int book;
	
	printf("gfs_lockMetadata(char *lock_mode, char *access_mode, int book, char *item_name, char *logical_loc)\n");
	
	printf("lock mode (x,s,xd): ");
	scanf("%s", &input);
	strcpy(lm, input);
	printf("access mode (wf,wd,rf,rd): ");
	scanf("%s", &input);
	strcpy(am, input);
	printf("book (1,0): ");
	scanf("%s", &input);
	book=atoi(input);
	printf("item name : ");
	scanf("%s", &input);
	strcpy(item, input);
	printf("logical loc: ");
	scanf("%s", &input);
	strcpy(lloc, input);

	return gfs_lockMetadata(lm,am,book,item,lloc);
}

int unlockmetadata()
{
	int pid, unbook;
	char item[128], lloc[256], input [256];
	
	printf("gfs_unlockMetadata(int pid, int unbook, char *item_name, char *logical_loc)\n");
	printf("pid(integer): ");
	scanf("%s", &input);
	pid=atoi(input);
	printf("unbook (1,0): ");
	scanf("%s", &input);
	unbook=atoi(input);
	printf("item name : ");
	scanf("%s", &input);
	strcpy(item, input);
	printf("logical loc: ");
	scanf("%s", &input);
	strcpy(lloc, input);
	return gfs_unlockMetadata(pid, unbook, item,lloc);
}

int checkerror(int iStatus)
{
	char strResult[100];
	
	switch(iStatus){
		case 1 : 
			strcpy(strResult, "GFS_SUCCESS");
			break;
		case 0 : 
			strcpy(strResult, "GFS_FAILED");
			break;
		// Trouble with connection
		case -1 :
			strcpy(strResult, "ECONN");
			break;
		// Trouble with service
		case -2 :
			strcpy(strResult, "ERNS");
			break;
		// Trouble with file
		case -11 : 
			strcpy(strResult, "EFNOTVALID");
			break;
		case -12 : 
			strcpy(strResult, "EFEXIST");
			break;
		// Trouble with directory
		case -21 : 
			strcpy(strResult, "EDNOTVALID");
			break;
		case -22 : 
			strcpy(strResult, "EDEXIST");
			break;
		case -23 : 
			strcpy(strResult, "EDNOTEMPTY");
			break;
		// Trouble with file or directory 
		case -31 : 
			strcpy(strResult, "EFDNOTVALID");
			break;
		case -32 : 
			strcpy(strResult, "EFDEXIST");
			break;
		// Trouble with permission & locking
		case -41 : 
			strcpy(strResult, "EPERMIT");
			break;
		case -42 : 
			strcpy(strResult, "ELOCK");
			break;
		default :
			break;	
	}
	
	if (iStatus<2)
	{
		printf(" (%s)\n", strResult);
	}
	else printf("\n");
	
}